#include <iostream>
#include <conio.h> 
#include <windows.h> 
#include <vector>
#include <ctime>

using namespace std;
using PII = pair<int, int>;


enum SnakeColor {
    COLOR_GREEN = 10,
    COLOR_RED = 12,
    COLOR_BLUE = 9,
    COLOR_YELLOW = 14,
    COLOR_PURPLE = 13,
    COLOR_CYAN = 11
};


bool gameOver;
bool returnToMenu = false;
const int width = 20;
const int height = 20;
int x, y, score;
int tim;
bool passThroughWalls;
clock_t gameStartTime;
clock_t fruitTimer;
clock_t specialFruitTimer;
bool specialFruitActive;
int specialFruitX, specialFruitY;
vector<PII> obstacles;
int fruitX, fruitY;
SnakeColor snakeColor = COLOR_GREEN;

vector<PII> snake;
enum eDirection { STOP = 0, LEFT, RIGHT, UP, DOWN };
eDirection dir;

// 设置控制台颜色
void SetColor(int color) {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}

// 重置为默认颜色
void ResetColor() {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}

void ShowColorMenu() {
    system("cls");
    cout << "==========================" << endl;
    cout << "     选择蛇的颜色       " << endl;
    cout << "==========================" << endl;

    SetColor(COLOR_GREEN);
    cout << "1. 绿色" << endl;

    SetColor(COLOR_RED);
    cout << "2. 红色" << endl;

    SetColor(COLOR_BLUE);
    cout << "3. 蓝色" << endl;

    SetColor(COLOR_YELLOW);
    cout << "4. 黄色" << endl;

    SetColor(COLOR_PURPLE);
    cout << "5. 紫色" << endl;

    SetColor(COLOR_CYAN);
    cout << "6. 青色" << endl;

    ResetColor();
    cout << "==========================" << endl;
    cout << "请选择颜色(1-6): ";
}

void ShowGameInstructions() {
    system("cls");
    cout << "==========================" << endl;
    cout << "       游戏说明         " << endl;
    cout << "==========================" << endl;
    cout << "1. 游戏目标：控制蛇吃到食物(F)，每吃一个得10分" << endl;
    cout << "2. 特殊食物(S)：出现时间短，吃到得30分" << endl;
    cout << "3. 障碍物(X)：碰到会结束游戏" << endl;
    cout << "4. 控制方式：" << endl;
    cout << "   - W/A/S/D 控制方向" << endl;
    cout << "   - P 暂停游戏" << endl;
    cout << "   - X 退出游戏" << endl;
    cout << "5. 游戏特性：" << endl;
    cout << "   - 游戏速度会随时间增加" << endl;
    cout << "   - 未及时吃掉的食物会变成障碍物" << endl;
    cout << "==========================" << endl;
    cout << "按任意键返回主菜单..." << endl;
    _getch();
}

void welcometogame() {
    while (true) {
        system("cls");
        cout << "==========================" << endl;
        cout << "       贪吃蛇游戏        " << endl;
        cout << "==========================" << endl;
        cout << "1. 开始游戏" << endl;
        cout << "2. 游戏说明" << endl;
        cout << "3. 退出游戏" << endl;
        cout << "==========================" << endl;
        cout << "请选择(1-3): ";

        char mainChoice = _getch();
        switch (mainChoice) {
        case '1': // 开始游戏
        {
            ShowColorMenu();
            char colorChoice = _getch();
            switch (colorChoice) {
            case '1': snakeColor = COLOR_GREEN; break;
            case '2': snakeColor = COLOR_RED; break;
            case '3': snakeColor = COLOR_BLUE; break;
            case '4': snakeColor = COLOR_YELLOW; break;
            case '5': snakeColor = COLOR_PURPLE; break;
            case '6': snakeColor = COLOR_CYAN; break;
            case 27: exit(0);
            default: snakeColor = COLOR_GREEN; break;
            }

            system("cls");
            cout << "选择游戏难度：A.快速 B.中速 C.慢速\n";
            char speedChoice = tolower(_getch());
            if (speedChoice >= '0' && speedChoice <= '9') {
                speedChoice = 'a' + speedChoice - '1';
            }
            if (speedChoice == 27) exit(0);
            switch (speedChoice) {
            case 'a': tim = 50; break;
            case 'b': tim = 100; break;
            case 'c': tim = 200; break;
            default: tim = 100; break;
            }

            cout << "选择模式：1.普通模式 2.穿墙模式\n";
            char modeChoice = _getch();
            if (modeChoice == 27) exit(0);
            passThroughWalls = (modeChoice == '2' || modeChoice == 'B' || modeChoice == 'b');

            return; // 开始游戏
        }
        case '2': // 游戏说明
            ShowGameInstructions();
            break;
        case '3': // 退出游戏
        case 27:  // ESC键
            exit(0);
        default:
            break;
        }
    }
}

void Setup() {
    gameOver = false;
    returnToMenu = false;
    dir = STOP;
    x = width / 2;
    y = height / 2;
    snake.clear();
    snake.push_back({ x, y });
    obstacles.clear();

    srand(time(0));
    fruitX = rand() % width;
    fruitY = rand() % height;
    specialFruitActive = false;

    score = 0;
    gameStartTime = clock();
    fruitTimer = clock();
}

void Draw() {
    system("cls");


    for (int i = 0; i < width + 1; i++)
        cout << "##";
    cout << endl;

    for (int i = 0; i < height; i++) {
        cout << "#";

        for (int j = 0; j < width; j++) {
            if (i == y && j == x) {
                SetColor(snakeColor);
                cout << " O";
                ResetColor();
            }
            else if (find(snake.begin() + 1, snake.end(), make_pair(j, i)) != snake.end()) {
                SetColor(snakeColor);
                cout << " o";
                ResetColor();
            }
            else if (i == fruitY && j == fruitX) {
                SetColor(12);
                cout << " F";
                ResetColor();
            }
            else if (specialFruitActive && i == specialFruitY && j == specialFruitX) {
                SetColor(14);
                cout << " S";
                ResetColor();
            }
            else if (find(obstacles.begin(), obstacles.end(), make_pair(j, i)) != obstacles.end()) {
                SetColor(8);
                cout << " X";
                ResetColor();
            }
            else {
                cout << "  ";
            }
        }

        cout << "#";
        cout << endl;
    }

    for (int i = 0; i < width + 1; i++)
        cout << "##";
    cout << endl;

    cout << "分数: " << score << endl;
    cout << "模式: " << (passThroughWalls ? "穿墙模式" : "普通模式") << endl;
    cout << "速度: " << (200 - tim) / 10 << "%" << endl;
}

void Input() {
    if (_kbhit()) {
        switch (tolower(_getch())) {
        case 'a':
            if (dir != RIGHT)
                dir = LEFT;
            break;
        case 'd':
            if (dir != LEFT)
                dir = RIGHT;
            break;
        case 'w':
            if (dir != DOWN)
                dir = UP;
            break;
        case 's':
            if (dir != UP)
                dir = DOWN;
            break;
        case 'p':
            while (true) {
                if (_kbhit() && tolower(_getch()) == 'p')
                    break;
                Sleep(100);
            }
            break;
        case 27: // ESC键
            gameOver = true;
            exit(0);
            break;
        case 'x':
            gameOver = true;
            exit(0);
            break;
        }
    }
}

void Logic() {
    PII prevTail = snake.back();

    for (size_t i = snake.size() - 1; i > 0; i--) {
        snake[i] = snake[i - 1];
    }

    switch (dir) {
    case LEFT:
        x--;
        break;
    case RIGHT:
        x++;
        break;
    case UP:
        y--;
        break;
    case DOWN:
        y++;
        break;
    default:
        break;
    }

    if (passThroughWalls) {
        if (x >= width) x = 0;
        if (x < 0) x = width - 1;
        if (y >= height) y = 0;
        if (y < 0) y = height - 1;
    }

    snake[0] = { x, y };

    if (x == fruitX && y == fruitY) {
        score += 10;
        snake.push_back(prevTail);
        fruitX = rand() % width;
        fruitY = rand() % height;
        fruitTimer = clock();
    }

    if (specialFruitActive && x == specialFruitX && y == specialFruitY) {
        score += 30;
        snake.push_back(prevTail);
        specialFruitActive = false;
    }

    if (!passThroughWalls && (x >= width || x < 0 || y >= height || y < 0))
        gameOver = true;

    for (size_t i = 1; i < snake.size(); i++) {
        if (snake[i].first == x && snake[i].second == y)
            gameOver = true;
    }

    for (auto obs : obstacles) {
        if (x == obs.first && y == obs.second) {
            gameOver = true;
            break;
        }
    }

    if ((clock() - gameStartTime) > 30000) {
        tim = max(30, tim * 9 / 10);
        gameStartTime = clock();
    }

    if ((clock() - fruitTimer) > 10000) {
        obstacles.push_back({ fruitX, fruitY });
        fruitX = rand() % width;
        fruitY = rand() % height;
        fruitTimer = clock();
    }

    if (!specialFruitActive && rand() % 100 == 0) {
        specialFruitX = rand() % width;
        specialFruitY = rand() % height;
        specialFruitActive = true;
        specialFruitTimer = clock();
    }

    if (specialFruitActive && (clock() - specialFruitTimer) > 8000) {
        obstacles.push_back({ specialFruitX, specialFruitY });
        specialFruitActive = false;
    }
}

void ShowGameOver() {
    system("cls");
    cout << "==========================" << endl;
    cout << "       游戏结束!         " << endl;
    cout << "       最终得分: " << score << endl;
    cout << "       蛇长度: " << snake.size() << endl;
    cout << "==========================" << endl;
    cout << "按任意键返回主菜单..." << endl;
    cout << "按ESC键退出游戏" << endl;
    Sleep(1000);
    int key = _getch();
    if (key == 27) {
        exit(0);
    }
    else {
        returnToMenu = true;
    }
}

int main() {
    while (true) {
        welcometogame();
        Setup();
        while (!gameOver) {
            Draw();
            Input();
            Logic();
            Sleep(tim);
        }
        ShowGameOver();
        if (returnToMenu) continue;
    }
    return 0;
}